/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.rum.sender;

import cz.muni.fi.rum.RumConfigurator;
import cz.muni.fi.rum.reflector.telnet.TelnetServer;
import cz.muni.fi.rum.sender.command.Factory.CommandFactory;
import cz.muni.fi.rum.sender.command.RapMessage;
import cz.muni.fi.rum.sender.command.RapRequest;
import cz.muni.fi.rum.sender.command.RapResponse;
import cz.muni.fi.rum.sender.command.history.CommandHistoryManager;
import cz.muni.fi.rum.sender.listener.DefaultSenderEvent;
import cz.muni.fi.rum.sender.listener.SenderEvent;
import cz.muni.fi.rum.sender.listener.SenderListener;
import cz.muni.fi.rum.sender.senders.MainSender;
import cz.muni.fi.rum.sender.senders.MessageSender;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jdesktop.application.Task;

/**
 *
 * @author pmikulasek
 */
public class SenderManagerImpl implements SenderManager {

    private static SenderManager instance;
    private CommandHistoryManager history = Factory.getHistoryManager();
    private CommandFactory commandFactory = Factory.getCommandFactory();
    private MainSender forceSender = Factory.getSenderFactory().getForceSender();
    private MainSender bufferSender = Factory.getSenderFactory().getBufferSender();
    private SenderMode mode;
    private List<SenderListener> listeners = new LinkedList<SenderListener>();

    @Override
    public void registerSenderListener(SenderListener listener) {
        if (!listeners.contains(listener)) {
            listeners.add(listener);
        }
    }

    @Override
    public MessageSender createAndConnectNewMessageSender(TelnetServer server) throws IOException {
        return Factory.getSenderFactory().createAndConnectNewMessageSender(server);
    }

    public static enum SenderMode {

        force, buffer
    }

    private SenderManagerImpl() {
        this.mode = SenderMode.buffer;
    }

    public static SenderManager getInstance() {
        if (instance == null) {
            instance = new SenderManagerImpl();
        }
        return instance;
    }

    @Override
    public synchronized void setMode(SenderMode mode) {
        this.mode = mode;
    }

    private void executeAllListeners(SenderEvent event) {
        for (SenderListener senderListener : listeners) {
            senderListener.actionPerformed(event);
        }
    }

    @Override
    public List<RapRequest> addRequest(String key, Map<String, String> params) throws SenderException {
        switch (mode) {
            case buffer:
                bufferSender.addRequest(commandFactory.createRequest(key, params));
                executeAllListeners(new DefaultSenderEvent(SenderEvent.Type.add, bufferSender.getAllRequests()));
                return bufferSender.getAllRequests();
            case force:
                forceSender.addRequest(commandFactory.createRequest(key, params));
                executeAllListeners(new DefaultSenderEvent(SenderEvent.Type.send));
                return forceSender.getAllRequests();
            default:
                throw new UnsupportedOperationException("Not supported this mode.");
        }
    }

    @Override
    public void removeRequest(RapRequest request) {
        if (mode.equals(SenderMode.buffer)) {
            bufferSender.removeRequest(request);
            executeAllListeners(new DefaultSenderEvent(SenderEvent.Type.remove, bufferSender.getAllRequests()));
        } else {
            throw new UnsupportedOperationException("Not supported in this mode.");
        }
    }

    @Override
    public Task sendAllRequest() {
        Task ret = null;
        if (mode.equals(SenderMode.buffer)) {
            ret = new Task<Void, Void>(RumConfigurator.getInstance()) {

                @Override
                protected Void doInBackground() throws Exception {
                    bufferSender.sendAllRequests();
                    return null;
                }

                @Override
                protected void succeeded(Void result) {
                    executeAllListeners(new DefaultSenderEvent(SenderEvent.Type.send));
                }
            };
//            bufferSender.sendAllRequests();
//            executeAllListeners(new DefaultSenderEvent(SenderEvent.Type.send));
        } else {
            throw new UnsupportedOperationException("Not supported in this mode.");
        }
        return ret;
    }

    @Override
    public Set<RapRequest> getAllExecutedRequests() {
        return history.getAllRequest();
    }

    @Override
    public List<RapMessage> getHistoryLog() {
        return history.getAllHistory();
    }

    @Override
    public RapResponse getResponseByRequestId(Long requestId) {
//        return getHistoryManager().getResponseByRequestId(requestId);
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public RapResponse getResponseByRequest(RapRequest request) throws Exception {
        return history.getResponseByRequest(request);
    }
}
